package la.iok.hzsvn.lewin.movie.core;

import com.fasterxml.jackson.annotation.JsonProperty;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.core.model.UserRoleVo;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.token.TokenBase;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Token extends TokenBase {
    /**
     * 登录用户id，如果是用户登录的话。非用户登录则为null
     */
    private Long userId;
    /**
     * 用户名
     */
    @JsonProperty("user_name")
    private String username;
    /**
     * 登录设备id,如果是设备登录的话.非设备登录则为null
     */
    private Long deviceId;
    /**
     * 用户所属组织。除了admin账号,其他都有组织
     */
    private Long orgUnitId;
    /**
     * 用户微信账号绑定id
     */
    private Long wxBindingId;
    /**
     * 用户角色列表
     */
    private List<UserRoleVo> userRoles;

    /**
     * 是否有其中某一项权限
     * @param roles 待测试权限列表
     * @return 如果包含其中任意一项权限,则返回true,如果一个都不包含,则返回false
     */
    public boolean hasAnyAuthority(RoleEnum... roles){
        return hasAnyAuthority(Arrays.stream(roles).map(RoleEnum::toString).distinct().toArray(String[]::new));
    }

    /**
     * 是否有指定的角色
     * @param role 角色
     * @return 拥有对应的角色返回true否则false
     */
    public boolean hasAuthority(@NotNull RoleEnum role){
        return hasAuthority(role.toString());
    }

    /**
     * 验证token是否具有任一权限。如果所有权限都没有，那就抛出{@link la.iok.hzsvn.share.protocol.exception.ErrorCodeException ErrorCodeException}异常
     * @param roles 角色列表
     */
    public void validAnyAuthority(RoleEnum... roles){
        ErrorCode.AUTHORITY_ERROR.assertTrue(hasAnyAuthority(roles), Stream.of(
                roles).map(RoleEnum::getDisplayName).collect(Collectors.joining(";")));
    }

    public void applyAuthorities(RoleEnum... roles){
        setAuthorities(Arrays.stream(roles).map(RoleEnum::name).collect(Collectors.toList()));
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Long getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(Long deviceId) {
        this.deviceId = deviceId;
    }

    public Long getOrgUnitId() {
        return orgUnitId;
    }

    public void setOrgUnitId(Long orgUnitId) {
        this.orgUnitId = orgUnitId;
    }

    public Long getWxBindingId() {
        return wxBindingId;
    }

    public void setWxBindingId(Long wxBindingId) {
        this.wxBindingId = wxBindingId;
    }

    public List<UserRoleVo> getUserRoles() {
        return userRoles;
    }

    public void setUserRoles(List<UserRoleVo> userRoles) {
        this.userRoles = userRoles;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Token token = (Token) o;
        return Objects.equals(userId, token.userId) && Objects.equals(deviceId, token.deviceId) && Objects.equals(orgUnitId, token.orgUnitId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, deviceId, orgUnitId);
    }

    @Override
    public String toString() {
        return "Token{" +
                "userId=" + userId +
                ", deviceId=" + deviceId +
                ", orgUnitId=" + orgUnitId +
                ", userRoles=" + userRoles +
                '}';
    }
}
